package com.ztesoft.zsmart.zcm.monitor.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.http.ResponseEntity;

import com.ztesoft.zsmart.core.exception.BaseAppException;
import com.ztesoft.zsmart.core.log.ZSmartLogger;
import com.ztesoft.zsmart.core.util.JsonUtil;
import com.ztesoft.zsmart.zcm.core.remote.RestClient;
import com.ztesoft.zsmart.zcm.monitor.config.MonitorProperties;
import com.ztesoft.zsmart.zcm.monitor.model.cmdb.ClusterDto;
import com.ztesoft.zsmart.zcm.monitor.model.cmdb.ServerDto;
import com.ztesoft.zsmart.zcm.monitor.utils.model.Cluster;
import com.ztesoft.zsmart.zcm.monitor.utils.model.K8sZone;

public final class RestClientUtil {
    private RestClientUtil() {
    }

    private static final String CMDB_URL = ((MonitorProperties) SpringContextUtil.getBean(MonitorProperties.class))
        .getCmdbBaseUrl();

    private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(RestClientUtil.class);

    /**
     * 租户查应用
     *
     * @param tenantIds
     * @return
     */
    public static List<Map> qryAppsByTenantId(List<Integer> tenantIds) {
        StringBuffer tIds = new StringBuffer();
        for (Integer tenantId : tenantIds) {
            if (tIds.length() < 1) {
                tIds.append("?tenantIds=").append(tenantId);
            }
            else {
                tIds.append("&tenantIds=").append(tenantId);
            }
        }
        List<Map> applicationDtos = new ArrayList<>();
        ResponseEntity<String> forEntity = SpringContextUtil.getBean(RestClient.class).getForEntity(
            new StringBuffer(CMDB_URL).append("/v1/applications/tenantIds").append(tIds).toString(), String.class);
        String body = forEntity.getBody();
        try {
            applicationDtos = JsonUtil.json2List(body, Map.class);
            applicationDtos.forEach(a -> {
                a.put("applicationId", a.get("referenceId"));
                a.put("applicationName", a.get("name"));
            });

        }
        catch (BaseAppException e) {
            LOGGER.error(e);
        }
        return applicationDtos;
    }

    /**
     * 租户查集群ID
     *
     * @param tenantId
     * @return
     */
    public static List<String> qryClusterIdsByTenantId(Integer tenantId) {
        ResponseEntity<String> entity = SpringContextUtil.getBean(RestClient.class)
            .getForEntity(new StringBuffer(CMDB_URL).append("/v1/tenants/").append(tenantId)
                .append("/clusters?pageSize=9999&pageNum=1").toString(), String.class);
        String body = entity.getBody();
        List<String> cIds = new ArrayList<>();
        try {
            Map<String, Object> page = JsonUtil.json2Map(body);
            List<Map<String, Object>> row = (List<Map<String, Object>>) page.get("list");
            row.forEach(m -> cIds.add(String.valueOf(m.get("clusterId"))));
        }
        catch (BaseAppException e) {
            LOGGER.error(e);
        }
        return cIds;
    }

    /**
     * 按项目查集群
     *
     * @param projectId
     * @return
     */
    public static List<Map> qryClusterByProjectId(Integer projectId) {
        ResponseEntity<String> entity = SpringContextUtil.getBean(RestClient.class).getForEntity(
            new StringBuffer(CMDB_URL).append("/v1/projects/").append(projectId).append("/clusters").toString(),
            String.class);
        List<Map> list = new ArrayList<>();
        try {
            list = JsonUtil.json2List(entity.getBody(), Map.class);
        }
        catch (BaseAppException e) {
            LOGGER.error("parse error", e);
        }
        return list;
    }

    /**
     * 按集群查主机
     *
     * @param clusterId
     * @return
     */
    public static List<ServerDto> qryServerByClusterId(Integer clusterId) {
        ResponseEntity<String> entity = SpringContextUtil.getBean(RestClient.class)
            .getForEntity(new StringBuffer(CMDB_URL).append("/v1/clusters/").append(clusterId)
                .append("/serversAssignedToCluster").toString(), String.class);
        List<ServerDto> list = new ArrayList<>();
        try {
            list = JsonUtil.json2List(entity.getBody(), ServerDto.class);
        }
        catch (BaseAppException e) {
            LOGGER.error("parse error", e);
        }
        return list;
    }

    /**
     * 执行单机脚本
     *
     * @param map
     * @return
     */
    public static ResponseEntity<String> remoteExec(Map<String, Object> map) {
        ResponseEntity<String> response = null;
        try {
            response = SpringContextUtil.getBean(RestClient.class).postForEntity(CMDB_URL + "/remote/exec",
                JsonUtil.object2Json(map), String.class);
        }
        catch (BaseAppException e) {
            LOGGER.error(e);
        }
        return response;
    }

    /**
     * 执行多机脚本
     *
     * @param cmdbJson
     * @return
     */
    public static ResponseEntity<String> remoteExecBatch(Map<String, Object> cmdbJson) {
        ResponseEntity<String> response = null;
        try {
            response = SpringContextUtil.getBean(RestClient.class).postForEntity(CMDB_URL + "/remote/exec/batch",
                JsonUtil.object2Json(cmdbJson), String.class);
        }
        catch (BaseAppException e) {
            LOGGER.error(e);
        }
        return response;
    }

    /**
     * 项目查clusterIds和zoneIds
     *
     * @param projectId
     * @return
     */
    public static Map qryClusterIdZoneIdByProjectId(Integer projectId) {
        RestClient restClient = SpringContextUtil.getBean(RestClient.class);

        List<Map> clusterIds = new ArrayList<>();

        try {
            List<Map> results = restClient.getForEntity(
                new StringBuffer(CMDB_URL).append("/v1/projects/").append(projectId).append("/clusters").toString(),
                List.class).getBody();

            clusterIds = results.stream().map(r -> {
                try {
                    return JsonUtil.json2Object(JsonUtil.map2Json(r), Cluster.class);
                }
                catch (BaseAppException e) {
                    LOGGER.error(e);
                }
                return new Cluster();
            }).collect(Collectors.toList()).stream().map(c -> {
                Map<String, Object> cluster = new HashMap<>();
                cluster.put("id", c.getClusterId());
                cluster.put("name", c.getClusterName());
                return cluster;
            }).collect(Collectors.toList());
        }
        catch (Exception e) {
            LOGGER.error(e);
        }
        List<Map> zoneIds = qryZoneByProjectId(projectId);
        Map<String, List> result = new HashMap<>();
        result.put("clusterIds", clusterIds);
        result.put("zoneIds", zoneIds);
        return result;
    }

    /**
     * 按项目查zone id name
     *
     * @param projectId
     * @return
     */
    public static List<Map> qryZoneByProjectId(Integer projectId) {
        List<Map> zoneIds = new ArrayList<>();
        RestClient restClient = SpringContextUtil.getBean(RestClient.class);
        try {
            List<Map> results = restClient.getForEntity(
                new StringBuffer(CMDB_URL).append("/v1/projects/").append(projectId).append("/zones").toString(),
                List.class).getBody();
            zoneIds = results.stream().map(r -> {
                try {
                    return JsonUtil.json2Object(JsonUtil.map2Json(r), K8sZone.class);
                }
                catch (BaseAppException e) {
                    LOGGER.error(e);
                }
                return new K8sZone();
            }).collect(Collectors.toList()).stream().map(k -> {
                Map<String, Object> zone = new HashMap<>();
                zone.put("id", k.getZoneId());
                zone.put("name", k.getZoneName());
                return zone;
            }).collect(Collectors.toList());
        }
        catch (Exception e) {
            LOGGER.error(e);
        }
        return zoneIds;
    }

    /**
     * zondId查主机信息
     *
     * @param zoneId
     * @return
     */
    public static List<ServerDto> qryServersByZoneId(Integer zoneId) {
        List<ServerDto> results = new ArrayList<>();
        try {
            List<Map> dtos = SpringContextUtil.getBean(RestClient.class)
                .getForEntity(new StringBuffer(CMDB_URL).append("/rpc/zones/servers/").append(zoneId).toString(),
                    List.class)
                .getBody();
            getServerList(results, dtos);

        }
        catch (Exception e) {
            LOGGER.error(e);
        }

        return results;
    }

    /**
     * 租户查主机
     *
     * @param tenantId
     * @return
     */
    public static List<ServerDto> qryServersByTenantId(Integer tenantId) {
        List<ServerDto> results = new ArrayList<>();
        try {
            Map result = SpringContextUtil.getBean(RestClient.class)
                .getForEntity(new StringBuffer(CMDB_URL).append("/v1/tenants/").append(tenantId)
                    .append("/servers?pageSize=99999&pageNum=1").toString(), Map.class)
                .getBody();
            List<Map> list = (List<Map>) result.get("list");
            getServerList(results, list);
        }
        catch (Exception e) {
            LOGGER.error(e);
        }
        return results;
    }

    public static List<ServerDto> qryShareK8sServers() {
        List<ServerDto> results = new ArrayList<>();
        try {
            List<Map> list = SpringContextUtil.getBean(RestClient.class).getForEntity(
                new StringBuffer(CMDB_URL).append("/k8sCluster/getShareK8sClusters").toString(), List.class).getBody();
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(c -> {
                    try {
                        List<Map> servers = SpringContextUtil.getBean(RestClient.class)
                            .getForEntity(new StringBuffer(CMDB_URL).append("/v1/clusters/")
                                .append(c.get("k8sClusterId")).append("/servers").toString(), List.class)
                            .getBody();
                        getServerList(results, servers);

                    }
                    catch (Exception e) {
                        LOGGER.error(e);
                    }
                });
            }
        }
        catch (Exception e) {
            LOGGER.error(e);
        }

        return results;
    }

    private static void getServerList(List<ServerDto> results, List<Map> servers) {
        if (CollectionUtils.isNotEmpty(servers)) {
            servers.forEach(r -> {
                try {
                    results.add(JsonUtil.json2Object(JsonUtil.map2Json(r), ServerDto.class));
                }
                catch (BaseAppException e) {
                    LOGGER.error(e);
                }
            });
        }
    }

    /**
     * CODE查项目
     *
     * @param projectCode
     * @return
     */
    public static Map qryProjectByCode(String projectCode) {
        RestClient restClient = SpringContextUtil.getBean(RestClient.class);
        Map results = new HashMap();
        try {
            results = restClient.getForEntity(
                new StringBuffer(CMDB_URL).append("/rpc/project/code?projectCode=").append(projectCode).toString(),
                Map.class).getBody();
        }
        catch (Exception e) {
            LOGGER.error(e);
        }
        return results;
    }

    /**
     * 项目Id查询主机
     *
     * @param projectId
     * @return
     */
    public static List<ServerDto> qryServersByProjectId(Integer projectId) {
        List<ServerDto> results = new ArrayList<>();
        try {
            List<Map> dtos = SpringContextUtil.getBean(RestClient.class).getForEntity(new StringBuffer(CMDB_URL)
                .append("/v1/projects/").append(projectId).append("/servers?page=1&size=9999").toString(), List.class)
                .getBody();
            if (dtos == null) {
                return results;
            }
            dtos.forEach(r -> {
                try {
                    results.add(JsonUtil.json2Object(JsonUtil.map2Json((Map) r.get("server")), ServerDto.class));
                }
                catch (BaseAppException e) {
                    LOGGER.error(e);
                }
            });

        }
        catch (Exception e) {
            LOGGER.error(e);
        }

        return results;
    }

    /**
     * ip模糊查主机，不准
     *
     * @param ip
     * @return
     */
    public static ServerDto qryServersByIp(String ip) {
        try {
            Map dto = SpringContextUtil.getBean(RestClient.class)
                .getForEntity(new StringBuffer(CMDB_URL).append("/rpc/server/qryServerByIp?ip=").append(ip).toString(),
                    Map.class)
                .getBody();
            return JsonUtil.json2Object(JsonUtil.map2Json((Map) dto.get("data")), ServerDto.class);
        }
        catch (Exception e) {
            LOGGER.error(e);
        }

        return new ServerDto();
    }

    /**
     * 主机Id查集群信息
     *
     * @param id
     * @return
     */
    public static List<ClusterDto> qryClusterByServerId(Integer id) {
        List<ClusterDto> results = new ArrayList<>();
        try {
            List<Map> dtos = SpringContextUtil.getBean(RestClient.class)
                .getForEntity(
                    new StringBuffer(CMDB_URL).append("/v1/servers/").append(id).append("/clusters").toString(),
                    List.class)
                .getBody();
            dtos.forEach(r -> {
                try {
                    results.add(JsonUtil.json2Object(JsonUtil.map2Json(r), ClusterDto.class));
                }
                catch (BaseAppException e) {
                    LOGGER.error(e);
                }
            });
            return results;
        }
        catch (Exception e) {
            LOGGER.error(e);
        }

        return results;
    }
}
